﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using Galaktika.BI.Silverlight.Runtime.Data.Olap;
using Ranet.Olap.Core.Data;
using Galaktika.BI.Silverlight.Runtime.Data;

namespace Galaktika.BI.Silverlight.ClientApp
{
    public class DataSourcePathResolver
    {
        #region resolvers

        private class PropertyResolver : DataSourcePathResolver
        {
            private object m_DataSource;
            public PropertyResolver(object dataSource)
            {
                m_DataSource = dataSource;
            }

            protected override object ResolveInternal(string path)
            {
                PropertyInfo prop = m_DataSource.GetType().GetProperty(path, BindingFlags.Public | BindingFlags.Instance);
                if (prop != null)
                {
                    return  prop.GetValue(m_DataSource, null);
                }
                return null;
            }
        }

        private class RanetOlapCoreDataCellSetDataResolver : DataSourcePathResolver
        {
            FlatDescriptionCollection m_FlatData;

            public RanetOlapCoreDataCellSetDataResolver(CellSetData dataSource)
            {
                m_FlatData = new FlatDescriptionCollection();
                if (dataSource.Axes.Count > 1)
                {
                    int colIndex = 0;
                    foreach (var column in dataSource.Axes[0].Positions)
                    {
                        int rowIndex = 0;
                        foreach (var row in dataSource.Axes[1].Positions)
                        {
                            if (column.Members.Count > 0)
                            {
                                FlatDescription flatObj = new FlatDescription();
                                //flatObj.Argument = column.Members[0].UniqueName;
                                flatObj.ArgumentSegments.Add(dataSource.Axes[0].Members[column.Members[0].Id].UniqueName);
                                flatObj.DisplayValue = dataSource.GetCellDescription(colIndex, rowIndex).Value.Value;
                                m_FlatData.Add(flatObj);
                            }
                            //rowIndex++;
                            // учитываем только первую строку
                            break;
                        }
                        colIndex++;
                    }
                }
            }

            protected override object ResolveInternal(string path)
            {
                FlatDescription flatObj = m_FlatData[path];
                if (flatObj == null)
                {
                    int index;
                    if (int.TryParse(path, out index))
                    {
                        flatObj = m_FlatData[index];
                    }
                }
                if (flatObj != null)
                {
                    return flatObj.DisplayValue;
                }
                return null;
            }
        }

        private class DataTableWrapperDataResolver : DataSourcePathResolver
        {
            DataTable m_DataTable;

            public DataTableWrapperDataResolver(DataTableWrapper dataSource)
            {
                m_DataTable = new DataTable();
                if (dataSource.Rows.Count > 1)
                {
                    m_DataTable = DataTable.Create(dataSource);
                }
            }

            protected override object ResolveInternal(string path, int index)
            {
                object result = null;
                int rowIndex = 0;
                int columnIndex = 0;                
                if (int.TryParse(path, out columnIndex))
                {
                    int i = 0;
                    foreach (var column in m_DataTable.Columns)
                    {
                        if (columnIndex == i)
                            path = column.Name;
                    }
                }
                if (!string.IsNullOrEmpty(path))
                {
                    foreach (var row in m_DataTable.Rows)
                    {
                        foreach (var cell in row)
                        {
                            if (cell.ColumnName.Equals(path) && rowIndex == index)
                            {
                                result = cell.Value;
                                break;
                            }
                        }
                        rowIndex++;
                    }
                }
                if (result != null)
                {
                    return result;
                }
                return null;
            }
        }

        #endregion

        private Dictionary<object, DataSourcePathResolver> m_Cache;
        public DataSourcePathResolver()
        {
            m_Cache = new Dictionary<object, DataSourcePathResolver>();
        }

        protected virtual object ResolveInternal(string path)
        {
            return null;
        }

        protected virtual object ResolveInternal(string path, int index)
        {
            return null;
        }

        private DataSourcePathResolver CreateResolver(object dataSource)
        {
            DataSourcePathResolver resolver = null;
            if (dataSource is Ranet.Olap.Core.Data.CellSetData)
            {
                resolver = new RanetOlapCoreDataCellSetDataResolver((CellSetData)dataSource);
                if ((dataSource as CellSetData).Axes.Count > 0)
                    this.m_Count = (dataSource as CellSetData).Axes[0].Positions.Count;
                else
                    this.m_Count = 0;
            }

            if (dataSource is DataTableWrapper)
            {
                resolver = new DataTableWrapperDataResolver((DataTableWrapper) dataSource);
                if ((dataSource as DataTableWrapper).Rows.Count > 0)
                    this.m_Count = (dataSource as DataTableWrapper).Rows.Count;
                else
                    this.m_Count = 0;
            }

            if (resolver == null)
            {
                resolver = new PropertyResolver(dataSource);
            }

            m_Cache.Add(dataSource, resolver);
            return resolver;
        }

        public object Resolve(object dataSource, string path, int index)
        {
            if (dataSource != null)
            {
                DataSourcePathResolver resolver;
                m_Cache.TryGetValue(dataSource, out resolver);
                if (resolver == null)
                {
                    resolver = this.CreateResolver(dataSource);
                }
                if (resolver is DataTableWrapperDataResolver)
                {
                    return resolver.ResolveInternal(path, index);
                }
                return resolver.ResolveInternal(path);
            }

            return null;
        }

        private int m_Count = 0;
        public int Count
        {
            get { return m_Count; }
        }

    }
}
